/*
 * Copyright (C) 2010 Yury Kudryashov.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package name.kudryashov.primitives;

import name.kudryashov.base.Argument;
import name.kudryashov.functions.NoArgsProcedure;
import name.kudryashov.functions.Procedure;

// TODO support for generators, ranges etc.
public class RichInt extends Number {

    private final Integer i;

    public RichInt(Integer i) {
        this.i = i;
    }

    public String toString(int radix) {
        return Integer.toString(i, radix);
    }

    public String toHexString() {
        return Integer.toHexString(i);
    }

    public String toOctalString() {
        return Integer.toOctalString(i);
    }

    public String toBinaryString() {
        return Integer.toBinaryString(i);
    }

    public static RichInt parseInt(String s, int radix) throws NumberFormatException {
        return new RichInt(Integer.parseInt(s, radix));
    }

    public static RichInt parseInt(String s) throws NumberFormatException {
        return new RichInt(Integer.parseInt(s));
    }

    public static RichInt valueOf(String s, int radix) throws NumberFormatException {
        return new RichInt(Integer.valueOf(s, radix));
    }

    public static RichInt valueOf(String s) throws NumberFormatException {
        return new RichInt(Integer.valueOf(s));
    }

    public static RichInt valueOf(int i) {
        return new RichInt(i);
    }

    public byte byteValue() {
        return i.byteValue();
    }

    public short shortValue() {
        return i.shortValue();
    }

    public int intValue() {
        return i;
    }

    public long longValue() {
        return i.longValue();
    }

    public float floatValue() {
        return i.floatValue();
    }

    public double doubleValue() {
        return i.doubleValue();
    }

    public String toString() {
        return Integer.toString(i);
    }

    public int hashCode() {
        return i.hashCode();
    }

    @SuppressWarnings({"EqualsWhichDoesntCheckParameterClass"})
    public boolean equals(Object obj) {
        return i.equals(obj);
    }

    public static RichInt getInteger(String nm) {
        return new RichInt(Integer.getInteger(nm));
    }

    public static RichInt getInteger(String nm, int val) {
        return new RichInt(Integer.getInteger(nm, val));
    }

    public static RichInt getInteger(String nm, Integer val) {
        return new RichInt(Integer.getInteger(nm, val));
    }

    public static RichInt decode(String nm) throws NumberFormatException {
        return new RichInt(Integer.decode(nm));
    }

    public int compareTo(Integer anotherInteger) {
        return i.compareTo(anotherInteger);
    }

    public int abs() {
        return Math.abs(i);
    }

    public int max(int that) {
        return Math.max(i, that);
    }

    public int min(int that) {
        return Math.min(i, that);
    }

/*  TODO
    public Range to(int to) {

    }


*/
    // TODO test below code

    public void times(Procedure<Integer> operation) {
        Argument.requireNotNull(operation, "operation");
        for(int count = 0; count < i; count++) {
            operation.call(count);
        }
    }

    public void times(NoArgsProcedure operation) {
        Argument.requireNotNull(operation, "operation");
        for(int count = 0; count < i; count++) {
            operation.call();
        }
    }
}